#include<stdio.h>
#include"asound.h"
#include<sys/ioctl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>


#define ELEM_MIC_PLAYBACK_ID      5
#define ELEM_MIC_MUTE_ID          27
#define ELEM_PLAYBACK_MUTE_ID     28
#define ELEM_HEADPHONE_MUTE_ID    15


int get_card_info( int fd, struct sndrv_ctl_card_info* info )
{

       if (ioctl( fd, SNDRV_CTL_IOCTL_CARD_INFO, info) < 0) {		
		printf( " SNDRV_CTL_IOCTL_CARD_INFO fail\n" );
		return -1;
	}


	printf( " card number is %d \n", info ->card );
	printf( " reserved for future is %d\n", info ->pad );
	printf( " id of card is   %s \n", info->id );
	printf( " Driver name is %s \n", info->driver );
	printf( " Short name  is %s \n", info->name );
	printf( " Long name  is %s \n", info->longname );
	printf( " visual mixer identification is %s \n",info->mixername );
	printf( " card components %s\n", info ->components );
	return 0;
}
int get_elem_info( int fd ,struct sndrv_ctl_elem_info* info )
{

	info ->id.numid =ELEM_PLAYBACK_MUTE_ID;//ELEM_MIC_MUTE_ID;// 25;	
       if (ioctl( fd, SNDRV_CTL_IOCTL_ELEM_INFO, info) < 0) {		
		printf( " SNDRV_CTL_IOCTL_ELEM_INFO fail %d\n", errno );
		return -1;
	}
	
	printf( " id->name is %s\n ", info ->id.name );	
	printf( " count is %d\n ", info ->count );
	return 0;
}

int get_elem_list( int fd, struct sndrv_ctl_elem_list* list )
{

	int i = 0;
	struct sndrv_ctl_elem_id* pid;
        if (ioctl( fd, SNDRV_CTL_IOCTL_ELEM_LIST, list) < 0) {		
		printf( " SNDRV_CTL_IOCTL_ELEM_LIST fail %d\n", errno );
		return -1;
	}
	
	/*printf( " offset  is %d\n", list ->offset );
	printf( " sapce   is %d\n", list ->space );
	printf( " used    is %d\n", list ->used );
	printf( " count   is %d\n", list ->count );
	printf( " reserv  is %s\n", list ->reserved );*/

	pid = list ->pids;
#if 1
	for( i = 0; i < list ->used; i++ ) {
		printf( " *****************************************\n" );
		printf( " numid    is %d\n", pid ->numid );
		printf( " iface    is %d\n", pid ->iface );
		printf( " device   is %d\n", pid ->device );
		printf( " name     is %s\n", pid ->name );
		printf( " index    is %d\n", pid ->index );
		pid++;
	
	}
#endif
	return 0;
}



int set_playback_mute( int fd, struct sndrv_ctl_elem_id* id )
{
        struct sndrv_ctl_elem_value control;
	
	printf( " nuid is %d  \n",id ->numid );
	control.id = *id;
	control.value.integer.value[0] = 1;
	//control.id.numid = ELEM_MIC_MUTE_ID;
        if (ioctl( fd,SNDRV_CTL_IOCTL_ELEM_WRITE, &control ) < 0) {		
		printf( " SNDRV_CTL_IOCTL_ELEM_WRITE fail %d\n", errno );
		return -1;
	}


	return 0;
}


int set_mic_playback_switch(int fd,  struct sndrv_ctl_elem_id* id )
{

        struct sndrv_ctl_elem_value control;
	
	printf( " nuid is %d  \n",id ->numid );
	control.id = *id;
	control.value.integer.value[0] = 0;
	//control.id.numid = ELEM_MIC_MUTE_ID;
        if (ioctl( fd,SNDRV_CTL_IOCTL_ELEM_WRITE, &control ) < 0) {		
		printf( " SNDRV_CTL_IOCTL_ELEM_WRITE fail %d\n", errno );
		return -1;
	}

	return 0;
}
int set_mic_to_playback( int fd,struct sndrv_ctl_elem_id* mic_id, struct sndrv_ctl_elem_id* playback_id )
{
        struct sndrv_ctl_elem_value control;
	
	printf( " nuid is %d and %d \n", mic_id ->numid, playback_id ->numid );

	//26
	control.id = *mic_id;

        if (ioctl( fd,SNDRV_CTL_IOCTL_ELEM_READ, &control ) < 0) {		
		printf( " SNDRV_CTL_IOCTL_ELEM_READ fail %d\n", errno );
		return -1;
	}
	printf( " prim value is %ld\n", control.value.integer.value[0] );

	control.value.integer.value[0] = 0;
        if (ioctl( fd,SNDRV_CTL_IOCTL_ELEM_WRITE, &control ) < 0) {		
		printf( " SNDRV_CTL_IOCTL_ELEM_WRITE fail %d\n", errno );
		return -1;
	}


        if (ioctl( fd,SNDRV_CTL_IOCTL_ELEM_READ, &control ) < 0) {		
		printf( " SNDRV_CTL_IOCTL_ELEM_READ fail %d\n", errno );
		return -1;
	}
	printf( " after value is %ld\n", control.value.integer.value[0] );
	

	//  27
	
	control.id = *playback_id;

        if (ioctl( fd,SNDRV_CTL_IOCTL_ELEM_READ, &control ) < 0) {		
		printf( " SNDRV_CTL_IOCTL_ELEM_READ fail %d\n", errno );
		return -1;
	}
	printf( " prim value is %ld\n", control.value.integer.value[0] );

	control.value.integer.value[0] = 1;
	//control.id.numid = ELEM_PLAYBACK_MUTE_ID;
        if (ioctl( fd,SNDRV_CTL_IOCTL_ELEM_WRITE, &control ) < 0) {		
		printf( " SNDRV_CTL_IOCTL_ELEM_WRITE fail %d\n", errno );
		return -1;
	}

        if (ioctl( fd,SNDRV_CTL_IOCTL_ELEM_READ, &control ) < 0) {		
		printf( " SNDRV_CTL_IOCTL_ELEM_READ fail %d\n", errno );
		return -1;
	}
	printf( " after value is %ld\n", control.value.integer.value[0] );

	return 0;
}
int main( int argc, char** argv )
{
	int fd = -1;
	struct sndrv_ctl_card_info info;
	struct sndrv_ctl_elem_info elem_info;
	struct sndrv_ctl_elem_list list;
	char* pid = NULL;
	struct sndrv_ctl_elem_id* elem_id;	
	struct sndrv_ctl_elem_id* elem_mic_mute_id;	
	struct sndrv_ctl_elem_id* elem_playback_mute_id;	
	struct sndrv_ctl_elem_id* elem_front_playback_mute_id;
	printf( "test control in alsa\n" );
	fd = open( "/dev/snd/controlC0",O_RDWR );
	if( -1 == fd ) {
		printf( "cann't open controlC0\n" );
		return -1;
	}
	
	//get_card_info( fd, &info );
	
	//elem_info.id = 1;
	//get_elem_info( fd, &elem_info );


	list.offset = 0;
	list.space  = 50;
	pid = ( char* ) malloc( list.space * sizeof( struct sndrv_ctl_elem_id ) );
	list.pids = ( struct sndrv_ctl_elem_id * ) pid;
	get_elem_list( fd, &list );	

	//printf( " size of *elem_id is %d, %d\n", sizeof( *elem_id ), sizeof( struct sndrv_ctl_elem_id ) );

	elem_id = ( struct sndrv_ctl_elem_id* ) ( list.pids + ( ELEM_MIC_PLAYBACK_ID - 1 ) );	
	elem_mic_mute_id = ( struct sndrv_ctl_elem_id* ) ( list.pids + ( ELEM_MIC_MUTE_ID - 1 ) );
	elem_playback_mute_id = ( struct sndrv_ctl_elem_id* ) ( list.pids +  ( ELEM_PLAYBACK_MUTE_ID - 1 ) );
	elem_front_playback_mute_id = ( struct sndrv_ctl_elem_id* ) ( list.pids +  ( ELEM_HEADPHONE_MUTE_ID - 1 ) );


	//set_mic_to_playback( fd, elem_mic_mute_id, elem_playback_mute_id );
	set_mic_playback_switch( fd, elem_id );
	//set_playback_mute( fd, elem_front_playback_mute_id );
	close( fd );
	free( pid );
	return 0;
}
